<?php
namespace app\process;

use Workerman\Timer;
use Workerman\Worker;
use support\Log;
use Webman\RedisQueue\Redis;

class BatchProcessor
{
    public function onWorkerStart(Worker $worker)
    {
        // 每10秒执行一次
        Timer::add(2, function() {
            $this->processBatch();
        });
    }
    
    protected function processBatch()
    {
        // 批处理逻辑
        $hour = date('H');//9;
        $minute = date('i'); //43;    
        try{
            if(in_array(date('w'), [6,0])){
                $msg = date('Y-m-d H:i:s')."---周末无需跑！\r\n"; 
                Log::info($msg); 
                throw new \Exception($msg);
            }
            if($hour != 9 ){
                $msg = date('Y-m-d H:i:s')."---".$hour.':'.$minute.",时间段不允许\r\n";
                Log::info($msg); 
                throw new \Exception($msg);
            }
            if($hour == 9 && $minute < 30){
                $msg = date('Y-m-d H:i:s')."---".$hour.':'.$minute.",时间段不允许\r\n";
                Log::info($msg); 
                throw new \Exception($msg);
            } 
            $okKey = 'buy3000w:ok:'.date("Y-m-d");
            if(Redis::exists($okKey)){
                $msg = date('Y-m-d H:i:s')."---".$hour.':'.$minute.",今日已经购买了 无许再跑批\r\n";
                Log::info($msg); 
                throw new \Exception($msg);
            }
            self::do_run();   
            $msg = date("Y-m-d H:i:s")."--------------------执行成功。\r\n";
            Log::info($msg); 
            echo $msg;
        }catch (\Exception $e){
            $msg = $e->getMessage();
            Log::info($msg); 
            echo $msg;
        }
    }
    
    /**
     * 爬取数据
     * @param unknown $page
     */
    public static function do_run()
    {
        $page = 1;
        $money = 30000000; //三千万
        $min_rise_fall = 1; //涨幅小于3
        $end = false;
        $the_date = date('Y-m-d');
        while ($end == false){
            $url = "https://push2.eastmoney.com/api/qt/clist/get?fid=f62&po=1&pz=50&pn=$page&np=1&fltt=2&invt=2&ut=b2884a393a59ad64002292a3e90d46a5&fs=m%3A0%2Bt%3A6%2Bf%3A!2%2Cm%3A0%2Bt%3A13%2Bf%3A!2%2Cm%3A0%2Bt%3A80%2Bf%3A!2%2Cm%3A1%2Bt%3A2%2Bf%3A!2%2Cm%3A1%2Bt%3A23%2Bf%3A!2%2Cm%3A0%2Bt%3A7%2Bf%3A!2%2Cm%3A1%2Bt%3A3%2Bf%3A!2&fields=f12%2Cf14%2Cf2%2Cf3%2Cf62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf204%2Cf205%2Cf124%2Cf1%2Cf13";
            //$url = "https://push2.eastmoney.com/api/qt/clist/get?cb=jQuery112307500466123838297_1745543193449&fid=f62&po=1&pz=50&pn=$page&np=1&fltt=2&invt=2&ut=8dec03ba335b81bf4ebdf7b29ec27d15&fs=m%3A0%2Bt%3A6%2Bf%3A!2%2Cm%3A0%2Bt%3A13%2Bf%3A!2%2Cm%3A0%2Bt%3A80%2Bf%3A!2%2Cm%3A1%2Bt%3A2%2Bf%3A!2%2Cm%3A1%2Bt%3A23%2Bf%3A!2%2Cm%3A0%2Bt%3A7%2Bf%3A!2%2Cm%3A1%2Bt%3A3%2Bf%3A!2&fields=f12%2Cf14%2Cf2%2Cf3%2Cf62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf204%2Cf205%2Cf124%2Cf1%2Cf13";
            $response = self::curlProxyGet($url); 
            $result_data = json_decode($response, true);
            if(empty($result_data) || !isset($result_data['data'])){
                $msg = "返回数据为".$response.",请求数据返回结果有误 \r\n";
                Log::info($msg); 
                echo $msg;
                break;
            }
            echo "[".$page."]\r\n"; 
            $datas = $result_data['data']['diff'];
            foreach ($datas as $key => $data){
                $code = substr($data['f12'], 0, 2);
                $top = 50 * ($page -1) + $key + 1;
                $gp_code = $data['f12'];
                $gp_name = $data['f14'];
                $price  =  ($data['f2']== '-') ? 0 : $data['f2'];
                $rise_fall = ($data['f3']== '-') ? 0 : $data['f3'];
                $zljlr_je  =  ($data['f62']== '-') ? 0 : $data['f62'];
                $zljlr_jzb =  ($data['f184']== '-') ? 0 : $data['f184'];
                if (strpos($gp_name, 'N') !== false) {
                    //不买新股
                }else if (strpos($gp_name, 'ST') !== false) {
                    //不买退市票
                }else if (strpos($gp_name, 'C') !== false) {
                    //不买次新股
                }else if (strpos($gp_name, '银行') !== false) {
                    //不买银行
                }else{
                    if($data['f62'] > $money && $data['f3'] <= $min_rise_fall
                        && $price >= 5 && $price <= 50 && !in_array($code, ['20','90','68'])){
                            $sanqianwanKey = "buy3000wGupiao:the_date:".$the_date.":gp_code:".$gp_code;
                            if(!Redis::exists($sanqianwanKey)){
                                $insert_data  = [
                                    'the_date' => $the_date,
                                    'top' => $top,
                                    'gp_code' => $gp_code,
                                    'gp_name' => $gp_name,
                                    'price' => $price,
                                    'rise_fall' => $rise_fall,
                                    'zljlr_je' => $zljlr_je,
                                    'zljlr_jzb' => $zljlr_jzb,
                                    'create_time' => date('Y-m-d H:i:s')
                                ];
                                $flag = self::buy3000w(2);
                                if($flag){
                                    //按照指定价格购买
                                    self::buy_gupiao_by_price($insert_data, 10000);
                                }else{
                                    $okKey = 'buy3000w:ok:'.date("Y-m-d");
                                    Redis::set($okKey, date("Y-m-d H:i:s"));
                                }
                                Redis::set($sanqianwanKey, date("Y-m-d H:i:s"));
                                Redis::expire($sanqianwanKey, 12*60*60);
                            }
                    }
                }
            }
            //二位数组最后一个数组
            $end_data = end($datas);
            if($end_data['f62'] < $money){
                $end = true;
            }
            $page++;
        }
    }
    
    
    
    /**
     * 指定价格买
     * @return string[]|mixed
     */
    public static function buy_gupiao_by_price($new_data, $money){
        //return true;
        $num = 0;
        $code = $new_data['gp_code'];
        $rise_fall = $new_data['rise_fall'];
        if(abs($rise_fall) > 7){
            $price = number_format($new_data['price']*1.015 + 0.01, 2, '.', '');
        }else if(abs($rise_fall) >4){
            $price = number_format($new_data['price']*1.01 + 0.01, 2, '.', '');
        }else{
            $price = number_format($new_data['price']*1.005 + 0.01, 2, '.', '');
        }
        //买数量
        if($money < 100000){
            $num =  ceil($money/($price * 100));
            $money = -100 *  $num;
        }  
        $mingling = "$code~2~1~9~$price~$money"; 
        $key = 'yiming_6XNXMBE951I39KETH9UT2CNNIK0FLAAA';
        Log::info($key."--------".$mingling."\r\n"); 
        Redis::lPush( $key, $mingling );
        $resultArray = explode('~', $mingling);
        if(is_array($resultArray)){
            $code = $resultArray[0];  //股票代码
            $flag = $resultArray[1];  //第几个券商   1，模拟1  2，东兴证券 3，银河证券
            $type = $resultArray[2];  //类型  1，买入   3卖出
            $pointMoney  = $resultArray[3];  //类型  9 指定价格
            $price  = $resultArray[4];  //类型  价格
            $number  = abs($resultArray[5]);  //购买数量  100的倍数
            //http://127.0.0.1:5000/buy?code=513060&price=0.43&amount=100
            $quanshangArr = [
                '1' => 'http://127.0.0.1:5000/',
                '2' => 'http://127.0.0.1:5001/',
                '3' => 'http://127.0.0.1:5002/'
            ];
            $requstUrl = "";
            if($type == 1){
                $requstUrl = $quanshangArr[$flag]."buy?code=".$code."&price=".$price."&amount=".$number;
            }
            if($type == 3){
                $requstUrl = $quanshangArr[$flag]."sell?code=".$code."&price=".$price."&amount=".$number;
            }
            $msg =  "url:".$requstUrl ."\r\n";
            Log::info($msg);
            echo $msg;
            if(!empty($requstUrl)){
                $ch = curl_init();    // 启动一个CURL会话
                curl_setopt($ch, CURLOPT_URL, $requstUrl);     // 要访问的地址
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  // 对认证证书来源的检查   // https请求 不验证证书和hosts
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);  // 从证书中检查SSL加密算法是否存在
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);     // 获取的信息以文件流的形式返回
                curl_setopt($ch, CURLOPT_TIMEOUT,2);
                $result = curl_exec($ch);
                curl_close($ch); // 关闭cURL会话
            }
            echo  "请求下单成功\r\n";
        }
    }
    
    
    
    /**
     * 请求连接
     * @param unknown $url
     * @return unknown
     */
    public static function curlProxyGet($url){
     
        $isException = 0;   
        try{
            echo "使用【file_get_contents】 方法请求。\r\n";
            $response = file_get_contents($url); 
            $isException =0;
        }catch (\Exception $e){
            $error = date('Y-m-d H:i:s')."---file_get_contents出现异常:code:".$e->getCode().',msg:'.$e->getMessage()."\r\n";
            $isException =1;
            $response = "";
            echo $error;
        } 
        
        if($isException == 1 || empty($response)){
            try{
                echo "使用【curlHeaderGet】 方法请求。\r\n";
                $response = self::curlHeaderGet($url);
                $isException =0;
            }catch (\Exception $e){
                $error = date('Y-m-d H:i:s')."---curlHeaderGet出现异常:code:".$e->getCode().',msg:'.$e->getMessage()."\r\n";
                $isException =1;
                $response = "";
                echo $error;
            }
        }
         
        if($isException == 1 || empty($response)){
            try{ 
                echo "使用【curlProxyGetNew】 方法请求。\r\n";
                $response =  self::curlProxyGetNew($url);
                $isException =0;
            }catch (\Exception $e){
                $error = date('Y-m-d H:i:s')."---curlProxyGetNew出现异常:code:".$e->getCode().',msg:'.$e->getMessage()."\r\n";
                $isException =1;
                echo $error;
                return "";
            }
        }
        
        
        return $response; 
    }
    
    
    public static function curlHeaderGet($url)
    {
        $ch = curl_init();
        $xforip = rand ( 1, 254 ) . "." . rand ( 1, 254 ) . "." . rand ( 1, 254 ) . "." . rand ( 1, 254 );
        echo "---------------使用模拟请求地址请求【".$xforip."】\r\n";
        $header [] = "X-FORWARDED-FOR: $xforip";
        $header [] = "CLIENT-IP: $xforip";
        curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header );
        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 2);
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,1);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 忽略主机名验证
        curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
        $res = curl_exec($ch);
        if (curl_errno($ch)) {
            echo "---------------使用模拟请求地址请求  返回结果errno:".curl_errno($ch)."curl_error:".curl_error($ch)."\r\n";
            curl_close($ch);
            return "";
        }
        echo "---------------使用模拟请求返回【".$res."】\r\n";
        curl_close($ch);
        return $res;
    }
    
    
    public static function curlProxyGetNew($url)
    {
        $ch = curl_init(); 
        $proxy = "120.25.1.15:7890"; // 代理IP:端口
        echo "-------------------------------使用代理IP请求【".$proxy."】\r\n";
        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 2);
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,1);
        curl_setopt($ch, CURLOPT_PROXY, $proxy); // 设置代理
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 忽略主机名验证
        curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");
        $res = curl_exec($ch);
        if (curl_errno($ch)) {
            echo "-------------------------------使用代理IP请求  返回结果errno:".curl_errno($ch)."curl_error:".curl_error($ch)."\r\n"; 
            curl_close($ch);
            return "";
        }
        echo "-------------------------------使用代理IP请求返回【".$res."】\r\n";
        curl_close($ch);
        return $res;
    }
    
    
    /**
     * 发送次数少于 $limit_num
     * @return string[]|mixed
     */
    public static function buy3000w($limit_num){
        $redis = new \Redis();
        $redis->connect('127.0.0.1','6379');
        $redis->auth('Sycs0PrusIuDkMNQ');
        $sendKey = date('Y-m-d').':buy3000w';
        $num = $redis->get($sendKey);
        if(empty($num)){
            $redis->set($sendKey, 1);
            return true;
        }else{
            $num = $num + 1;
            if($num > $limit_num){
                return false;
            } else{
                $redis->set($sendKey, $num);
                return true;
            }
        }
    }
}